package com.jingbian.cppccbackend.controller.admin;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.OSSObject;
import com.jingbian.cppccbackend.entity.Proposals;
import com.jingbian.cppccbackend.entity.Result;
import com.jingbian.cppccbackend.service.admin.ProposalsService;
import com.jingbian.cppccbackend.utils.ResultUtil;
import com.jingbian.cppccbackend.entity.vo.PageVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;


/**
 * <p>
 * 提案信息表——管理员操作 前端控制器
 * </p>
 *
 * @author yezi
 * @since 2025-02-11
 */
@Slf4j
@RestController
@Validated
@RequestMapping("/admins/proposals")
public class adminProposalsController {

    @Autowired
    private ProposalsService proposalsService;

    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    
    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId;
    
    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret;
    
    @Value("${aliyun.oss.bucketName}")
    private String bucketName;


    /**
     * 获取某个提案的详情
     * @param proposalId 提案ID
     * @return Proposals
     */
    @GetMapping("/getProposalById/{proposalId}")
    public Result<Proposals> getProposalById(@PathVariable Integer proposalId) {
        Proposals proposals = proposalsService.getProposalById(proposalId);
        return ResultUtil.success(proposals);
    }


    /**
     * 根据搜索文本搜索提案
     * @param searchText 搜索文本
     * @return List<Proposals>
     */
    @GetMapping("/search")
    public Result<List<Proposals>> searchProposals(@RequestParam(required = false) String searchText) {
        List<Proposals> proposals = proposalsService.searchProposals(searchText);
        return ResultUtil.success(proposals);
    }

    /**
     * [流程]获取所有提案数据及其关联的附件和联名人信息
     * @return List<Proposals>
     */
    @GetMapping("/getAllProposals")
    public Result<PageVO<Proposals>> getAllProposals(
            Integer pageNum,
            Integer pageSize,
            @RequestParam(required = false) String status,
            @RequestParam(required = false) String proposalType,
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate,
            @RequestParam(required = false, defaultValue = "desc") String sort,
            @RequestParam(required = false) String department,
            @RequestParam(required = false) String searchText,
            @RequestParam(required = false, defaultValue = "0") Integer pageStatus
    ) {
        PageVO<Proposals> proposals = proposalsService.getAllProposalsWithDetails(
                pageNum, pageSize, status, proposalType, startDate, endDate, sort,department, searchText,pageStatus);
        return ResultUtil.success(proposals);
    }

    /**
     * [流程]修改提案状态
     * @param proposalId 提案ID
     * @param status 新状态
     * @param isOr 是否通过
     * @param pageStatus 页面状态
     * @param department 分流部门（仅分流时需要）
     * @param handing_result 专项结果（仅提案专项处理时需要）
     * @param filePaths 文件路径
     * @return Result<String>
     */
    @PutMapping("/updateProposalStatus/{proposalId}")
    public Result<String> updateProposalStatus(
            @PathVariable Integer proposalId,
            @RequestParam String status,
            @RequestParam Boolean isOr,
            @RequestParam(required = false) String department,
            @RequestParam(required = false) String handing_result,
            @RequestParam(required = false) List<String> filePaths,
            @RequestParam(required = false) String fileName,
            @RequestParam(required = false) String size,
            @RequestParam(required = false, defaultValue = "0") Integer pageStatus
    ) {
        proposalsService.updateProposalStatus(proposalId, status, isOr, pageStatus, department, handing_result, filePaths, fileName, size);
        return ResultUtil.success("状态更新成功");
    }

    //    退回
    @PutMapping("/senBack/{proposalId}")
    public Result<String> senBack(
            @PathVariable Integer proposalId,
            @RequestParam String status,
            @RequestParam Boolean isOr,
            @RequestParam(required = false) String department,
            @RequestParam(required = false, defaultValue = "0") Integer pageStatus
    ) {
        proposalsService.senBack(proposalId, status, isOr, pageStatus, department);
        return ResultUtil.success("数据退回成功");
    }
    //公示
    @PutMapping("/publicity/{proposalId}")
    public Result<String> publicity(
            @PathVariable Integer proposalId,
            @RequestParam String status,
            @RequestParam Boolean isOr
    ) {
        proposalsService.publicity(proposalId, status, isOr);
        return ResultUtil.success("公示成功");
    }


    // 获取提案统计数据
    @GetMapping("/statistics")
    public Result<Map<String, Object>> getProposalStatistics() {
        return ResultUtil.success(proposalsService.getProposalStatistics());
    }

    // 获取提案类型分布
    @GetMapping("/typeDistribution")
    public Result<List<Map<String, Object>>> getProposalTypeDistribution() {
        return ResultUtil.success(proposalsService.getProposalTypeDistribution());
    }

    // 获取提案提交趋势 - 修改为支持日期范围
    @GetMapping("/trend")
    public Result<List<Map<String, Object>>> getProposalTrend(
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate) {
        return ResultUtil.success(proposalsService.getProposalTrend(startDate, endDate));
    }

    // 导出提案变化趋势数据
    @GetMapping("/exportTrendData")
    public ResponseEntity<byte[]> exportTrendData(
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate
    ) throws IOException {
        log.info("开始导出提案变化趋势数据，参数：startDate={}, endDate={}", startDate, endDate);

        try {
            // 获取提案趋势数据
            List<Map<String, Object>> trendData = proposalsService.getProposalTrend(startDate, endDate);
            log.info("获取到 {} 条趋势数据", trendData.size());

            // 创建工作簿
            try (XSSFWorkbook workbook = new XSSFWorkbook()) {
                Sheet sheet = workbook.createSheet("提案变化趋势");

                // 设置表头样式
                CellStyle headerStyle = workbook.createCellStyle();
                headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
                headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                Font headerFont = workbook.createFont();
                headerFont.setBold(true);
                headerStyle.setFont(headerFont);

                // 创建表头
                Row headerRow = sheet.createRow(0);
                String[] header = {"日期", "新增提案数量"};

                for (int i = 0; i < header.length; i++) {
                    Cell cell = headerRow.createCell(i);
                    cell.setCellValue(header[i]);
                    cell.setCellStyle(headerStyle);
                    sheet.autoSizeColumn(i);
                }

                // 填充数据
                int rowNum = 1;
                for (Map<String, Object> data : trendData) {
                    Row row = sheet.createRow(rowNum++);
                    row.createCell(0).setCellValue(data.get("date").toString());
                    row.createCell(1).setCellValue(Integer.parseInt(data.get("value").toString()));
                }

                // 写入字节数组
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                workbook.write(outputStream);
                byte[] content = outputStream.toByteArray();

                // 设置响应头
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
                String filename = URLEncoder.encode("提案变化趋势数据.xlsx", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
                headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + filename);

                log.info("Excel文件生成成功，大小: {} bytes", content.length);
                return new ResponseEntity<>(content, headers, HttpStatus.OK);
            }
        } catch (Exception e) {
            log.error("导出Excel失败", e);
            throw new RuntimeException("导出Excel失败: " + e.getMessage());
        }
    }

    /**
     * 统一的提案导出接口，根据pageStatus确定导出不同页面的数据
     * @param status 状态筛选
     * @param proposalType 提案类型
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @param sort 排序方式
     * @param department 部门
     * @param searchText 搜索文本
     * @param pageStatus 页面状态（1:初审，2:复审，3:分流，4:专项处理，5:督办，6:最终批复，7:提案查询）
     * @return Excel文件的字节流
     */
    @GetMapping("/exportProposals")
    public ResponseEntity<byte[]> exportProposals(
            @RequestParam(required = false) String status,
            @RequestParam(required = false) String proposalType,
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate,
            @RequestParam(required = false, defaultValue = "desc") String sort,
            @RequestParam(required = false) String department,
            @RequestParam(required = false) String searchText,
            @RequestParam(required = false, defaultValue = "0") Integer pageStatus
    ) throws IOException {
        log.info("开始导出提案列表，参数：status={}, proposalType={}, startDate={}, endDate={}, sort={}, department={}, searchText={}, pageStatus={}", 
                status, proposalType, startDate, endDate, sort, department, searchText, pageStatus);

        try {
            // 获取提案数据列表
            List<Proposals> proposalsList = proposalsService.getProposalsExportList(
                    status, proposalType, startDate, endDate, sort, department, searchText, pageStatus);
            log.info("获取到 {} 条数据", proposalsList.size());

            // 创建工作簿
            try (XSSFWorkbook workbook = new XSSFWorkbook()) {
                Sheet sheet = workbook.createSheet("提案列表");

                // 设置表头样式
                CellStyle headerStyle = workbook.createCellStyle();
                headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
                headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                Font headerFont = workbook.createFont();
                headerFont.setBold(true);
                headerStyle.setFont(headerFont);

                // 根据pageStatus设置不同的时间列名
                String timeColumnName;
                switch (pageStatus) {
                    case 1: // 初审
                        timeColumnName = "提交时间";
                        break;
                    case 2: // 复审
                        timeColumnName = "初审时间";
                        break;
                    case 3: // 分流
                        timeColumnName = "复审时间";
                        break;
                    case 4: // 专项处理
                    case 5: // 督办
                        timeColumnName = "分流时间";
                        break;
                    case 6: // 最终批复
                        timeColumnName = "专项处理时间";
                        break;
                    case 7: // 提案查询
                    default:
                        timeColumnName = "提交时间";
                        break;
                }

                // 创建表头
                Row headerRow = sheet.createRow(0);
                String[] header = {"提案号", "案由", "提案类型", "提案人", timeColumnName, "状态"};
                if (pageStatus == 3 || pageStatus == 4 || pageStatus == 5) {
                    // 如果是分流、专项处理或督办页面，添加部门列
                    header = new String[]{"提案号", "案由", "提案类型", "提案人", timeColumnName, "部门", "状态"};
                }

                for (int i = 0; i < header.length; i++) {
                    Cell cell = headerRow.createCell(i);
                    cell.setCellValue(header[i]);
                    cell.setCellStyle(headerStyle);
                }

                // 设置日期格式
                CellStyle dateStyle = workbook.createCellStyle();
                CreationHelper createHelper = workbook.getCreationHelper();
                dateStyle.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-mm-dd hh:mm:ss"));

                // 填充数据
                int rowNum = 1;
                for (Proposals proposal : proposalsList) {
                    Row row = sheet.createRow(rowNum++);
                    
                    int cellIdx = 0;
                    row.createCell(cellIdx++).setCellValue(proposal.getPid() != null ? proposal.getPid().toString() : "");
                    row.createCell(cellIdx++).setCellValue(proposal.getCaseReason() != null ? proposal.getCaseReason() : "");
                    row.createCell(cellIdx++).setCellValue(proposal.getProposalType() != null ? proposal.getProposalType() : "");
                    row.createCell(cellIdx++).setCellValue(proposal.getProposer() != null ? proposal.getProposer() : "");
                    
                    // 根据pageStatus选择不同的时间字段
                    Cell timeCell = row.createCell(cellIdx++);
                    LocalDateTime timeValue = null;
                    switch (pageStatus) {
                        case 1: // 初审
                            timeValue = proposal.getSubmitTime();
                            break;
                        case 2: // 复审
                            timeValue = proposal.getFirstAuditTime();
                            break;
                        case 3: // 分流
                            timeValue = proposal.getRecheckTime();
                            break;
                        case 4: // 专项处理
                        case 5: // 督办
                            timeValue = proposal.getShuntTime();
                            break;
                        case 6: // 最终批复
                            timeValue = proposal.getSpecialHandlingTime();
                            break;
                        case 7: // 提案查询
                        default:
                            timeValue = proposal.getSubmitTime();
                            break;
                    }
                    
                    if (timeValue != null) {
                        timeCell.setCellValue(java.sql.Timestamp.valueOf(timeValue));
                        timeCell.setCellStyle(dateStyle);
                    }
                    
                    // 如果是分流、专项处理或督办页面，添加部门信息
                    if (pageStatus == 3 || pageStatus == 4 || pageStatus == 5) {
                        row.createCell(cellIdx++).setCellValue(proposal.getDepartment() != null ? proposal.getDepartment() : "");
                    }
                    
                    row.createCell(cellIdx).setCellValue(proposal.getStatus() != null ? proposal.getStatus() : "");
                }

                // 自动调整列宽
                for (int i = 0; i < header.length; i++) {
                    sheet.autoSizeColumn(i);
                }

                // 写入字节数组
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                workbook.write(outputStream);
                byte[] content = outputStream.toByteArray();

                // 设置响应头
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
                
                // 根据pageStatus设置不同的文件名
                String filePrefix;
                switch (pageStatus) {
                    case 1: filePrefix = "初审提案"; break;
                    case 2: filePrefix = "复审提案"; break;
                    case 3: filePrefix = "分流提案"; break;
                    case 4: filePrefix = "专项处理提案"; break;
                    case 5: filePrefix = "督办提案"; break;
                    case 6: filePrefix = "最终批复提案"; break;
                    case 7: filePrefix = "全部提案"; break;
                    default: filePrefix = "提案"; break;
                }
                
                String filename = URLEncoder.encode(filePrefix + "列表.xlsx", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
                headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + filename);

                log.info("Excel文件生成成功，大小: {} bytes", content.length);
                return new ResponseEntity<>(content, headers, HttpStatus.OK);
            }
        } catch (Exception e) {
            log.error("导出Excel失败", e);
            throw new RuntimeException("导出Excel失败: " + e.getMessage());
        }
    }

    /**
     * 导出提案详情为Word文档
     * @param proposalId 提案ID
     * @return Word文档的资源流
     * @throws IOException 如果发生IO异常
     */
    @GetMapping("/exportProposalDetail/{proposalId}")
    public ResponseEntity<Resource> exportProposalDetail(@PathVariable Integer proposalId) throws IOException {
        log.info("开始导出提案详情到Word，提案ID: {}", proposalId);
        
        try {
            // 获取提案详情
            Proposals proposal = proposalsService.getProposalById(proposalId);
            if (proposal == null) {
                log.error("未找到提案，ID: {}", proposalId);
                return ResponseEntity.notFound().build();
            }
            
            // 准备数据
            Map<String, String> data = new HashMap<>();
            
            // 创建时间格式化函数
            Function<Object, String> formatTime = time ->
                time != null ?
                    time.toString()
                        .replace("T", " ")
                        .substring(0, 16)
                    : "";
            
            // 处理联名人
            String signers = proposal.getSigners() != null ? proposal.getSigners() : "无";
            
            // 填充数据
            data.put("pid", proposal.getPid() != null ? proposal.getPid().toString() : "");
            data.put("reason", proposal.getCaseReason() != null ? proposal.getCaseReason() : "");
            data.put("type", proposal.getProposalType() != null ? proposal.getProposalType() : "");
            data.put("uname", proposal.getProposer() != null ? proposal.getProposer() : "");
            data.put("signers", signers);
            data.put("region", proposal.getProposerRegion() != null ? proposal.getProposerRegion() : "");
            data.put("result", proposal.getHandingResult() != null ? proposal.getHandingResult() : "");
            data.put("content", proposal.getProposalContent() != null ? proposal.getProposalContent() : "");
            data.put("address", proposal.getAddress() != null ? proposal.getAddress() : "");
            data.put("topic", proposal.getTopic() != null ? proposal.getTopic() : "");
            data.put("will", proposal.getOrganizerWill() != null ? proposal.getOrganizerWill() : "");
            data.put("phone", proposal.getPhone() != null ? proposal.getPhone() : "");
            data.put("affiliation", proposal.getAffiliation() != null ? proposal.getAffiliation() : "");
            data.put("postalCode", proposal.getPostalCode() != null ? proposal.getPostalCode() : "");
            
            // 生成Word文档
            ByteArrayResource resource = proposalsService.generateProposalDoc(data);
            
            // 设置响应头
            String filename = URLEncoder.encode("提案" + proposalId + "_详情.docx", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
            
            log.info("Word文档生成成功，提案ID: {}", proposalId);
            
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + filename)
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .body(resource);
        } catch (Exception e) {
            log.error("导出Word文档失败", e);
            throw new RuntimeException("导出Word文档失败: " + e.getMessage());
        }
    }

    @GetMapping("/file/download")
    public ResponseEntity<byte[]> downloadFile(@RequestParam String url) {
        try {
            // 使用OSS客户端下载文件
            OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
            String objectKey = getObjectKeyFromUrl(url);
            log.info("Downloading file from OSS. ObjectKey: {}", objectKey);
            
            OSSObject ossObject = ossClient.getObject(bucketName, objectKey);
            byte[] content = IOUtils.toByteArray(ossObject.getObjectContent());
            
            // 从URL中获取文件名
            String fileName = objectKey.substring(objectKey.lastIndexOf("/") + 1);
            
            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDisposition(ContentDisposition.builder("attachment")
                    .filename(fileName, StandardCharsets.UTF_8)
                    .build());
            headers.setCacheControl("no-cache, no-store, must-revalidate");
            headers.setPragma("no-cache");
            headers.setExpires(0);
            
            log.info("File downloaded successfully. Size: {} bytes", content.length);
            
            return ResponseEntity.ok()
                    .headers(headers)
                    .body(content);
                    
        } catch (Exception e) {
            log.error("下载文件失败: {}", e.getMessage(), e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    // 从URL获取对象键的辅助方法
    private String getObjectKeyFromUrl(String url) {
        try {
            // 首先检查是否是完整URL
            if (url.startsWith("http")) {
                // 从完整URL中提取对象键
                String domainPart = bucketName + "." + endpoint.replace("https://", "").replace("http://", "");
                if (url.contains(domainPart)) {
                    return url.substring(url.indexOf(domainPart) + domainPart.length() + 1);
                }
            }

            // 如果不是完整URL或无法解析，尝试另一种方式
            if (url.contains("/")) {
                return url.substring(url.lastIndexOf("/") + 1);
            }

            // 如果都不成功，返回原始URL
            return url;
        } catch (Exception e) {
            log.error("提取对象键失败: {}", url, e);
            return url;
        }
    }

}
